﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Data.Entity;

using SosData;
using System.Linq.Expressions;
using System.Data.SqlClient;
using System.Data.Entity.Infrastructure;
using System.Reflection;

namespace SosBL
{
    public static class DataBL
    {
        /// <summary>
        /// Guardar cambios de la entidad
        /// </summary>
        /// <param name="entidad">entidad</param>
        /// <param name="context">context</param>
        /// <param name="state"></param>
        /// <returns>Items saved</returns>
        public static void GuardarCambios(object entidad, EntityState state)
        {
            using (sosContext db = new sosContext())
            {
                context.Dispose();
                var _entidad = (EntityBase)db.Entry(entidad).Entity;

                db.Entry(entidad).State = state;

                LineasAfectadas = db.SaveChanges();
            }
            context = new sosContext();
        }

        public static int LineasAfectadas { get; set; }

        /// <UserAdd>
        /// Add user object
        /// </UserAdd>
        /// <param name="name">Name</param>
        /// <param name="nickName">Nickname - alias</param>
        /// <param name="password">Password</param>
        /// <returns>SaveChanges</returns>
        public static void UserAdd(string name, string nickName, string password, string email)
        {
            Usuario u = new Usuario();
            u.Name = name;
            u.NickName = nickName;
            u.Password = password;
            u.email = email;
            GuardarCambios(u, EntityState.Added);
        }

        /// <UserEdit>
        /// Edit user object
        /// </summary>
        /// <param name="user">User object</param>
        /// <param name="context">DbContext</param>
        /// <returns>saveChanges()</returns>
        public static int UserEdit(Usuario user, sosContext context)
        {
            Usuario u = user;
            return context.SaveChanges();
        }

        /// <Get Users>
        /// Get users
        /// </summary>
        /// <param name="criteria">Where clause</param>
        /// <returns>list User</returns>
        public static List<Usuario> GetUsersList()
        {
            var context = new sosContext();
            var query = from u in context.Users select u;

            return query.ToList();
        }

        /// <PlantillAdd>
        /// Añadir nueva plantilla
        /// </summary>
        /// <param name="nombre">nombre plantilla</param>
        /// <param name="keywords">keywords</param>
        /// <param name="descripcion">descripcion</param>
        /// <returns>savechanges</returns>
        public static int AddPlantilla(string nombre, string keywords, string descripcion)
        {
            Plantilla plant = new Plantilla();
            plant.Keywords = keywords;
            plant.Nombre = nombre;
            plant.Descripcion = descripcion;

            var context = new sosContext();
            context.Plantillas.Add(plant);

            return context.SaveChanges();
        }

        /// <summary>
        /// Eliminar plantilla
        /// </summary>
        /// <param name="plantilla">Plantilla</param>
        /// <returns>SaveChanges()</returns>
        public static void DeletePlantilla(Plantilla plantilla)
        {
            using (var db = new sosContext())
            {
                db.Entry(plantilla).State = EntityState.Deleted;
                db.SaveChanges();
            }
        }

        /// <Getplantillas>
        /// Get Plantillas
        /// </Getplantillas>
        /// <returns>list plantillas</returns>
        public static List<Plantilla> GetPlantillaList()
        {
            using (var db = new sosContext())
            {
                var query = from p in db.Plantillas select p;

                return query.ToList();
                //return query.AsNoTracking().ToList();
            }
        }

        /// <Getplantillas>
        /// Get Plantillas
        /// </Getplantillas>
        /// <returns>list plantillas</returns>
        public static List<Plantilla> GetPlantillaListByGroup(string NombreGrupo)
        {
            using (var db = new sosContext())
            {
                var query = from p in db.Plantillas where (p.Grupo == NombreGrupo) select p;

                return query.ToList();
                //return query.AsNoTracking().ToList();
            }
        }


        /// <summary>
        /// Duplicar plantilla contenido
        /// </summary>
        /// <param name="plantillaContenido">PlantillaContenido</param>
        /// <returns>SaveChanges()</returns>
        public static void DuplicarPlantillaContenido(PlantillaContenido plantillaContenido)
        {
            using (var db = new sosContext())
            {
                var plantilla = (from p in db.Plantillas.Where(p => p.Id == plantillaContenido.Plantillas.Id) select p).FirstOrDefault();
                PlantillaContenido pc = new PlantillaContenido();
                pc.Idioma = plantillaContenido.Idioma;
                pc.Nombre = plantillaContenido.Nombre + " - copia";

                foreach (PlantillaParametro par in plantillaContenido.Parametros)
                {
                    PlantillaParametro p = new PlantillaParametro();
                    p.Nombre = par.Nombre;
                    p.Valor = par.Valor;
                    pc.Parametros.Add(p);
                }

                pc.Texto = plantillaContenido.Texto;
                pc.Tipologia = plantillaContenido.Tipologia;
                pc.Descripcion = plantillaContenido.Descripcion;
                pc.Plantillas = plantilla;
                db.PlantillaContenidos.Add(pc);

                db.SaveChanges();
            }

        }

        /// <summary>
        /// Get Plantilla by Id
        /// </summary>
        /// <param name="PlantillaId">PlantillaId</param>
        /// <returns>Plantilla</returns>
        public static Plantilla GetPlantillaById(int PlantillaId)
        {
            using (var db = new sosContext())
            {
                var query = from p in db.Plantillas where p.Id == PlantillaId select p;

                return query.FirstOrDefault();
            }
        }

        public static sosContext context { get; set; }

        /// <summary>
        /// Find plantilla by keywords, descripcion, nombre
        /// </summary>
        /// <param name="criteria"></param>
        /// <returns></returns>
        public static List<PlantillaContenido> FindPlantillas(string criteria)
        {
            List<PlantillaContenido> plantillasContenidos = new List<PlantillaContenido>();

            using (var db = new sosContext())
            {
                var Plantillas = from p in db.Plantillas.Include("PlantillaContenidos") where (p.Keywords.ToLower().Contains(criteria) || p.Nombre.ToLower().Contains(criteria) || p.Descripcion.ToLower().Contains(criteria)) select p;

                foreach (Plantilla item in Plantillas.ToList())
                {
                    if (item.PlantillaContenidos.Any())
                    {
                        plantillasContenidos = (from pc in item.PlantillaContenidos where (pc.Descripcion.ToLower().Contains(criteria) || pc.Nombre.ToLower().Contains(criteria) || pc.Descripcion.ToLower().Contains(criteria)) select pc).ToList();
                    }
                }

                return plantillasContenidos.ToList();
            }
        }

        /// <summary>
        /// Get PlantillaContenidos
        /// </summary>
        /// <param name="_plantilla"></param>
        /// <returns>List PlantillaContenidas</returns>
        public static List<PlantillaContenido> GetPlantillaContenidoByPlantilla(Plantilla _plantilla)
        {
            var query = _plantilla.PlantillaContenidos;

            if (query != null)
            {
                query.ToList();
            }

            return query;
        }

        /// <summary>
        /// Get PlantillaContenido by id
        /// </summary>
        /// <param name="PlantillaContenidoId">PlantillaContenidoId</param>
        /// <returns>PlantillaContenido</returns>
        public static PlantillaContenido GetPlantillaContenidoById(int PlantillaContenidoId)
        {
            PlantillaContenido _plantillaContenido;

            using (var db = new sosContext())
            {
                _plantillaContenido = (from pc in db.PlantillaContenidos.Include(pc => pc.Parametros).Include(pc => pc.Plantillas) where pc.Id == PlantillaContenidoId select pc).FirstOrDefault();

                return _plantillaContenido;
            }
        }

        /// <summary>
        ///  Get parametros de la plantillaContenido
        /// </summary>
        /// <param name="plantillaContenido">PlantillaContenido</param>
        /// <returns>cadena de los parametros</returns>
        public static string GetParametrosPlantillaContenido(PlantillaContenido plantillaContenido)
        {
            string param = "";

            using (var db = new sosContext())
            {
                PlantillaContenido _pc = (from pc in db.PlantillaContenidos.Where(pc => pc.Id == plantillaContenido.Id).Include("Parametros") select pc).FirstOrDefault();

                if (_pc.Parametros.Any())
                {
                    foreach (PlantillaParametro parametro in _pc.Parametros)
                    {
                        param = param + parametro.Nombre + ",";
                    }

                    if (param.Length > 0 && param != "")
                    {
                        param = param.Trim().Substring(0, param.Trim().Length - 1); //Sacamos la ultima coma de la cadena.
                    }
                }
            }
            return param;
        }

        /// <summary>
        /// Eliminar PlantillaContenido
        /// </summary>
        /// <param name="plantillaContenido">plantillaContenido</param>
        /// <returns>SaveChanges()</returns>
        public static void DeletePlantillaContenido(PlantillaContenido plantillaContenido)
        {
            using (var db = new sosContext())
            {
                db.PlantillaContenidos.Remove(plantillaContenido);
                db.SaveChanges();
            }
        }

        private static List<PlantillaContenido> plantillasEncontradas;

        /// <summary>
        /// Encontrar plantillaContenido por consulta
        /// </summary>
        /// <param name="consulta">consulta</param>
        /// <returns>list plantillaContenidos</returns>
        public static List<PlantillaContenido> BuscarPlantillaByConsulta(string consulta, PlantillaContenido.Idiomas idioma)
        {
            string _consulta = consulta.Trim().ToLower();

            plantillasEncontradas = new List<PlantillaContenido>();

            using (var db = new sosContext())
            {
                var plantContenidos = from p in db.PlantillaContenidos where p.Idioma == idioma select p;

                foreach (PlantillaContenido item in plantContenidos)
                {
                    string[] nombres = item.Nombre.Split("".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    foreach (string nombrePlant in nombres)
                    {
                        PlantillaEncontrada(_consulta, nombrePlant, item);
                    }

                    string[] descripciones = item.Descripcion.Split("".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    foreach (string descripcionPlant in descripciones)
                    {
                        PlantillaEncontrada(_consulta, descripcionPlant, item);
                    }
                }
            }

            return plantillasEncontradas;
        }

        private static void PlantillaEncontrada(string consulta, string texto, PlantillaContenido item)
        {
            if (consulta.Contains(texto.ToLower()))
            {
                if (!plantillasEncontradas.Exists(p => p.Id == item.Id))
                {
                    plantillasEncontradas.Add(item);
                }

            }
        }

        /// <summary>
        /// Generar plantilla con los valores parametros
        /// </summary>
        /// <param name="Texto">texto con parametros</param>
        /// <param name="parametros">Parametros</param>
        /// <returns></returns>
        public static string GenerarPlantilla(string Texto, List<PlantillaParametro> parametros)
        {
            string OutputText = Texto;
            using (var db = new sosContext())
            {
                foreach (PlantillaParametro parametro in parametros)
                {
                    try
                    {
                        if (parametro.Nombre.Contains("#"))
                        {
                            string param = parametro.Nombre.Substring(1, parametro.Nombre.Length - 2);

                            string textoPlantilla = (from t in db.PlantillaContenidos.Where(t => t.Nombre == param) select t).FirstOrDefault().Texto;
                            OutputText = OutputText.Replace("#" + param + "#", textoPlantilla);
                        }

                        if (parametro.Nombre.Contains("{"))
                        {
                            OutputText = OutputText.Replace(parametro.Nombre, parametro.Valor);
                        }
                    }
                    catch { }
                }
            }

            return OutputText;

        }

        public static void ComprobarSiParametrosIncluidos(string Texto, List<PlantillaParametro> parametros)
        {
            string OutputText = Texto;
            foreach (PlantillaParametro parametro in parametros)
            {
                if (!OutputText.Contains(parametro.Nombre))
                {
                    MessageBox.Show(String.Format("El parametro {0} no se encuentra en el texto.", parametro.Nombre));
                    break;
                }
            }
        }



        /// <Create formStatus if not exists>
        /// Create form status if not exists. 
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public static void CreateFormIfnotExist(Form form)
        {
            FormStatus frm = new FormStatus();
            frm.Form = form.Name;
            frm.Height = form.Height;
            frm.Width = form.Width;
            frm.TopPosition = form.Top;
            frm.LeftPosition = form.Left;

            if (form.WindowState == FormWindowState.Maximized)
            {
                frm.Maximized = true;
            }

            using (var db = new sosContext())
            {
                Usuario _user = new Usuario();
                _user = (Usuario)(from u in db.Users where u.Id == SosData.Parameters.UserId select u).FirstOrDefault();
                frm.user = _user;

                db.FormsStatus.Add(frm);
                db.SaveChanges();
                //GuardarCambios(frm, EntityState.Added);
            }
        }

        /// <FormStatus edit>
        /// Edit Formstatus
        /// </summary>
        /// <param name="form">Formstatus</param>
        /// <returns>SaveChanges()</returns>
        public static int FormStatusEdit(Form f)
        {
            using (var db = new sosContext())
            {
                FormStatus frm = (from form in db.FormsStatus where form.Form == f.Name && form.user.Id == SosData.Parameters.UserId select form).FirstOrDefault();
                frm.Height = f.Height;
                frm.Width = f.Width;
                frm.LeftPosition = f.Left;
                frm.TopPosition = f.Top;

                if (f.WindowState == FormWindowState.Maximized)
                {
                    frm.Maximized = true;
                }

                db.Entry(frm).State = EntityState.Modified;

                return db.SaveChanges();
            }
        }

        /// <GetFormStatus>
        /// Get form status
        /// </GetFormStatus>
        /// <param name="form"></param>
        /// <returns>FormStatus</returns>
        public static FormStatus GetFormStatus(Form form)
        {
            using (var db = new sosContext())
            {
                try
                {
                    IQueryable<FormStatus> query = from f in db.FormsStatus select f;

                    query = from f in db.FormsStatus where f.user.Id == Parameters.UserId && f.Form == form.Name select f;

                    if (!query.Any())
                    {
                        CreateFormIfnotExist(form);
                    }
                    return query.ToList().FirstOrDefault();
                }
                catch { return null; }
            }

        }

        /// <summary>
        /// Check if credentials are correct
        /// </summary>
        /// <param name="user">user</param>
        /// <param name="password">passord</param>
        /// <returns>boolean</returns>
        public static bool Login(string user, string password)
        {
            using (var db = new sosContext())
            {
                var users = from us in db.Users where us.NickName == user select us;
                bool result = false;

                if (users.Any())
                {
                    Usuario u = users.FirstOrDefault();

                    if (u.Password == password)
                    {
                        Parameters.UserId = u.Id;
                        Parameters.UserNickName = u.NickName;
                        result = true;
                    }
                    if (u.Password == null)
                    {
                        result = true;
                    }
                }
                return result;
            }
        }

        /// <Filterdata>
        /// Filter any object 
        /// </Filterdata>
        /// <typeparam name="T">object data</typeparam>
        /// <param name="criteria">criteria string. Name = "Administrador"</param>
        /// <returns>List</returns>
        public static List<T> Filter<T>(Type entidad, object campo, string criteria, string operador)
        {
            //if (criteria != "" || criteria != string.Empty)
            //{
            //    criteria = " and " + criteria;
            //}

            //string query = string.Format("SELECT * FROM {0} where 1=1 and {1}{2}{3}", entidad.Name, campo, operador,criteria);//@p0 = 'abc'";//and @p0='@p1'";
            string query = "Select * From PlantillaContenido where 1=1";
            SqlParameter sqlparam = new SqlParameter("@paramCriteria", criteria);

            var db = new sosContext();

            var results = db.Database.SqlQuery(entidad, query);
            //var results = db.Database.SqlQuery<PlantillaContenido>(query,sqlparam);

            return results.Cast<T>().ToList();// results.Cast<PlantillaContenido>().ToList(); ; // results.Cast<PlantillaContenido>().ToList();
        }

        /// <Filterdata>
        /// Filter any object 
        /// </Filterdata>
        /// <typeparam name="T">object data</typeparam>
        /// <param name="criteria">criteria string. Name = "Administrador"</param>
        /// <returns>List</returns>
        public static DbRawSqlQuery Filter(Type entidad, object campo, string criteria, string operador)
        {
            //if (criteria != "" || criteria != string.Empty)
            //{
            //    criteria = " and " + criteria;
            //}

            //string query = string.Format("SELECT * FROM {0} where 1=1 and {1}{2}{3}", entidad.Name, campo, operador,criteria);//@p0 = 'abc'";//and @p0='@p1'";
            SqlParameter sqlparam = new SqlParameter("paramCriteria", criteria);

            // string query = string.Format("Select * From PlantillaContenido where 1=1 and {0}{1}@paramCriteria", campo, operador);//, sqlparam);

            var db = new sosContext();

            if (operador == "=")
            {
                operador = "LIKE";
            }
            var results = db.Database.SqlQuery(entidad, string.Format("Select * From PlantillaContenido where {0} {1} @p0", campo, operador), criteria);
            //var results = db.Database.SqlQuery(entidad, string.Format("Select * From PlantillaContenido where {0} Like @p0", campo), criteria);


            return results;
        }

        /// <summary>
        /// Get properties
        /// </summary>
        /// <param name="entidad">entidad</param>
        /// <returns>list</returns>
        public static List<string> GetProperties(Type entidad)
        {
            List<string> propiedades = new List<string>();

            foreach (PropertyInfo item in entidad.GetProperties())
            {
                propiedades.Add(item.Name);
            }

            return propiedades;
        }
    }


   


}
